package com.pdx.shiro;

import com.alibaba.fastjson.JSON;
import com.pdx.constant.Constant;
import com.pdx.exception.BusinessException;
import com.pdx.exception.code.BaseResponseCode;
import com.pdx.utils.DataResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.OutputStream;

/**
 * @author PDX
 * @website https://blog.csdn.net/Gaowumao
 * @Date 2022-05-02 10:37
 * @Description
 */
@Slf4j
public class CustomAccessControlFilter extends AccessControlFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        /*
        * 此方法如果返回true，就流转到下一个链式调用
        * 返回false，就会流转到onAccessDenied方法
        *
        * */
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest servletRequest = (HttpServletRequest) request;
        log.info("request 接口地址：{}",servletRequest.getRequestURI());
        log.info("request 接口的请求方式：{}",servletRequest.getMethod());
        String token = servletRequest.getHeader(Constant.ACCESS_TOKEN);
        try {
            if (StringUtils.isEmpty(token)){
                throw new BusinessException(BaseResponseCode.TOKEN_NOT_NULL);
            }
            CustomUsernamePasswordToken accessToken = new CustomUsernamePasswordToken(token);
            getSubject(request,response).login(accessToken);
        }catch (BusinessException e){//系统抛出异常
            customResponse(response,e.getCode(),e.getMsg());
            return false;
        }catch (AuthorizationException e){//认证异常
            if (e.getCause() instanceof BusinessException){//判断抛出异常是否为系统异常
                BusinessException exception = ((BusinessException) e.getCause());
                customResponse(response,exception.getCode(),exception.getMsg());
            }else {
                customResponse(response,BaseResponseCode.TOKEN_ERROR.getCode(), BaseResponseCode.TOKEN_ERROR.getMsg());
            }
            return false;
        }catch (Exception e){
            customResponse(response,BaseResponseCode.SYSTEM_ERROR.getCode(), BaseResponseCode.SYSTEM_ERROR.getMsg());
            return false;
        }
        return true;
    }

    /**
     * 自定义响应前端
     * @param response
     * @param code
     * @param msg
     */
    private void customResponse(ServletResponse response,int code ,String msg){
        try {
            DataResult result= DataResult.getResult(code,msg);
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.setCharacterEncoding("UTF-8");
            String str= JSON.toJSONString(result);
            OutputStream outputStream=response.getOutputStream();
            outputStream.write(str.getBytes("UTF-8"));
            outputStream.flush();
        } catch (IOException e) {
            log.error("customResponse...error:{}",e);
        }

    }
}
